﻿//using System;
//using System.Collections.Generic;
//using System.Data;
//using System.Data.Entity;
//using System.Linq;
//using System.Threading;
//using UCosmic.Domain;
//using UCosmic.Domain.People;
//using UCosmic.Orm;

//namespace UCosmic.Storage
//{
//    public class PersonStorage : IStorePeople
//    {
//        #region Construction & DI

//        //public PersonStorage(IUnitOfWork unitOfWork)
//        //    : base(unitOfWork)
//        //{
//        //}

//        public IUnitOfWork UnitOfWork { get; private set; }

//        private UCosmicContext DbContext
//        {
//            get { return UnitOfWork as UCosmicContext; }
//        }

//        public PersonStorage(IUnitOfWork unitOfWork)
//        {
//            UnitOfWork = unitOfWork;
//        }

//        #endregion
//        #region Get / Read

//        public IEnumerable<Person> Find(PersonFinder finder)
//        {
//            // do not track entities returned by find methods
//            var query = DbContext.People.AsQueryable();

//            // initialize finder
//            if (finder == null)
//                finder = new PersonFinder();

//            // apply context tracking
//            if (!finder.IsForInsertOrUpdate)
//                query = query.AsNoTracking();

//            // apply includes
//            var includes = finder.ToBeEagerLoaded;
//            if (includes != null && includes.Count > 0)
//                query = finder.ToBeEagerLoaded.Aggregate(query, (lastInclude, nextInclude) =>
//                    lastInclude.Include(nextInclude));

//            // apply current, archived, and deleted switches
//            if (finder.IsCurrent.HasValue)
//                query = query.Where(role => role.IsCurrent == finder.IsCurrent.Value);
//            if (finder.IsArchived.HasValue)
//                query = query.Where(role => role.IsArchived == finder.IsArchived.Value);
//            if (finder.IsDeleted.HasValue)
//                query = query.Where(role => role.IsDeleted == finder.IsDeleted.Value);

//            // apply entity id
//            if (finder.EntityId.HasValue && finder.EntityId != Guid.Empty)
//                query = query.Where(role => role.EntityId == finder.EntityId);

//            // apply revision id
//            if (finder.RevisionId.HasValue && finder.RevisionId != 0)
//                query = query.Where(role => role.RevisionId == finder.RevisionId);

//            // apply email address
//            if (finder.EmailAddress != null)
//            {
//                query = query.Where(p => p.Emails.Any(e => 
//                    e.IsCurrent && !e.IsArchived && !e.IsDeleted
//                        && e.Value.Equals(finder.EmailAddress, StringComparison.OrdinalIgnoreCase)));
//            }

//            // apply email confirmation token
//            if (finder.EmailConfirmationToken != null && finder.EmailConfirmationToken != Guid.Empty
//                && !string.IsNullOrWhiteSpace(finder.EmailConfirmationIntent))
//            {
//                query = query.Where(p => p.Emails.Any(e =>
//                    e.IsCurrent && !e.IsArchived && !e.IsDeleted && e.Confirmations.Any(c => 
//                        c.Token == finder.EmailConfirmationToken.Value 
//                            && c.Intent == finder.EmailConfirmationIntent)));
//            }

//            var found = query.ToList();
//            return found;
//        }

//        public Person Get(PersonFinder finder)
//        {
//            return Find(finder).SingleOrDefault();
//        }

//        #endregion
//        public void InsertOrUpdate(Person person)
//        {
//            DbContext.Entry(person).State = (person.RevisionId == 0)
//                ? EntityState.Added
//                : EntityState.Modified;
//        }
//        #region Person Aggregate Root

//        private IQueryable<Person> All
//        {
//            get { return DbContext.People; }
//        }

//        public IQueryable<Person> Current
//        {
//            get
//            {
//                return All
//                    .Include(p => p.User)
//                    .Include(p => p.Emails)
//                    .Include(p => p.Emails.Select(e => e.Confirmations))
//                    .Include(p => p.Affiliations)
//                .Current();
//            }
//        }

//        //public override IQueryable<Person> AllIncluding(params Expression<Func<Person, object>>[] includeProperties)
//        //{
//        //    return includeProperties.Aggregate<Expression<Func<Person, object>>, IQueryable<Person>>(
//        //        DbContext.People, (current, includeProperty) => current.Include(includeProperty));
//        //}

//        //public Person Find(int id)
//        //{
//        //    return DbContext.People.Find(id);
//        //}

//        public void Refresh(Person entity)
//        {
//            DbContext.Entry(entity).State = (entity.RevisionId == default(int))
//                ? EntityState.Added
//                : EntityState.Modified;
//        }

//        public Person Revise(Person revisableEntity)
//        {
//            if (revisableEntity == null) return null;

//            var existingEntity = DbContext.People.Find(revisableEntity.RevisionId);
//            if (existingEntity == null)
//            {
//                Refresh(revisableEntity);
//                existingEntity = revisableEntity;
//            }
//            else
//            {
//                var existingEntry = DbContext.Entry(existingEntity);
//                existingEntry.CurrentValues.SetValues(revisableEntity);
//                existingEntity.CreatedOnUtc = DateTime.UtcNow;
//                existingEntity.CreatedByPrincipal = Thread.CurrentPrincipal.Identity.Name;
//                var originalEntity = existingEntry.OriginalValues.ToObject() as Person;
//                if (originalEntity != null)
//                {
//                    originalEntity.IsCurrent = false;
//                    DbContext.People.Add(originalEntity);
//                }
//            }

//            // enforce derived display name
//            existingEntity.DisplayName = (existingEntity.IsDisplayNameDerived)
//                ? existingEntity.DeriveDisplayName()
//                : existingEntity.DisplayName;

//            return existingEntity;
//        }

//        #endregion
//        #region Affiliation

//        public Affiliation Revise(Affiliation revisableEntity)
//        {
//            if (revisableEntity == null) return null;
//            var existingEntity = DbContext.People
//                .ByAffiliation(revisableEntity.RevisionId)
//                .Affiliations.ByRevisionId(revisableEntity.RevisionId);
//            if (existingEntity == null)
//            {
//                // TODO: write insert code
//            }
//            else
//            {
//                var existingEntry = DbContext.Entry(existingEntity);
//                existingEntry.CurrentValues.SetValues(revisableEntity);
//                if (!existingEntity.IsClaimingEmployee)
//                {
//                    existingEntity.IsClaimingAdministrator = false;
//                    existingEntity.IsClaimingFaculty = false;
//                    existingEntity.IsClaimingStaff = false;
//                    existingEntity.JobTitles = null;
//                }
//            }
//            return existingEntity;
//        }

//        #endregion
//        #region EmailAddress

//        /*
//         * Note: Ganesh, I have removed this method. 
//         * We can reafactor to encapsulate this in a repository later.
//         */
//        //public EmailAddress Revise(EmailAddress revisableEntity)
//        //{
//        //    if (revisableEntity == null) return null;
//        //    var existingEntity = DbContext.People
//        //        .ByEmail(revisableEntity.RevisionId)
//        //        .Emails.ByRevisionId(revisableEntity.RevisionId);
//        //    // .ByEmail(email)
//        //    //.Emails.ByEntityId(revisableEntity.EntityId);

//        //    //if (revisableEntity == null) return null;
//        //    //var existingEntity = DbContext.People
//        //    //    .ByAffiliation(revisableEntity.RevisionId)
//        //    //    .Affiliations.ByRevisionId(revisableEntity.RevisionId);

//        //    if (existingEntity == null)
//        //    {
//        //        // TODO: write insert code
//        //    }
//        //    else
//        //    {
//        //        var existingEntry = DbContext.Entry(existingEntity);
//        //        existingEntry.CurrentValues.SetValues(revisableEntity);
//        //        //if (!existingEntity.IsClaimingEmployee)
//        //        //{
//        //        //    existingEntity.IsClaimingAdministrator = false;
//        //        //    existingEntity.IsClaimingFaculty = false;
//        //        //    existingEntity.IsClaimingStaff = false;
//        //        //    existingEntity.JobTitles = null;
//        //        //}
//        //    }
//        //    return existingEntity;
//        //}

//        #endregion
//    }
//}
